function initGL(canvas) {
    try {
        gl = canvas.getContext("experimental-webgl");
        gl.viewportWidth = canvas.width;
        gl.viewportHeight = canvas.height;
      } catch(e) {
      }
      if (!gl) {
        alert("Could not initialise WebGL, sorry :-(");
      }
  return gl;
}


function getShader(gl, id) {
	
    var shaderScript = document.getElementById(id);
    if (!shaderScript) {
      return null;
    }

    var str = "";
    var k = shaderScript.firstChild;
    while (k) {
      if (k.nodeType == 3) {
        str += k.textContent;
      }
      k = k.nextSibling;
    }

    var shader;
    if (shaderScript.type == "x-shader/x-fragment") {
      shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (shaderScript.type == "x-shader/x-vertex") {
      shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
      return null;
    }

    gl.shaderSource(shader, str);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      alert(gl.getShaderInfoLog(shader));
      return null;
    }

    return shader;
}


function initShaders(gl) {
    var fragmentShader = getShader(gl, "shader-fs");
    var vertexShader = getShader(gl, "shader-vs");

    var shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);

    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
      alert("Could not initialise shaders");
    }

    gl.useProgram(shaderProgram);

    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

    shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
    gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);

    shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
    gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);

    shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
    shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
    shaderProgram.nMatrixUniform = gl.getUniformLocation(shaderProgram, "uNMatrix");
    shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
    shaderProgram.useLightingUniform = gl.getUniformLocation(shaderProgram, "uUseLighting");
    shaderProgram.ambientColorUniform = gl.getUniformLocation(shaderProgram, "uAmbientColor");
    shaderProgram.lightingDirectionUniform = gl.getUniformLocation(shaderProgram, "uLightingDirection");
    shaderProgram.directionalColorUniform = gl.getUniformLocation(shaderProgram, "uDirectionalColor");
    return shaderProgram;
}

function log(value) {
	document.getElementById("log").innerHTML = value;
}

function drawScene(gl, shaderProgram, table) {

	finishDrawing = 0;
	
	  //alert("test" + table);
	  //alert(table[0].vertexBuffer);
    gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    var maxX = - 1000, maxY = - 1000, maxZ = - 1000;
	var minX = 10000, minY = 10000, minZ = 10000;
	for(i in table.p)
	{
		 maxX = Math.max(maxX, table.p[i].x);
		 maxY = Math.max(maxY, table.p[i].y);
		 maxZ = Math.max(maxZ, table.p[i].z);
		 
		 minX = Math.min(minZ, table.p[i].x);
		 minY = Math.min(minY, table.p[i].y);
		 minZ = Math.min(minZ, table.p[i].z);
	}
    
    perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);
    loadIdentity();
    
	var xyz = Math.sqrt(moveMouseX * moveMouseX + moveMouseY * moveMouseY + moonTranformation * moonTranformation);

	var xy = Math.sqrt(moveMouseX * moveMouseX + moveMouseY * moveMouseY);
	
	var alfa = Math.acos(xy/xyz);

	mvTranslate([(maxX + minX), 0, 0]);
	
	var newZ = Math.sin(alfa) * moonTranformation;
	var newX = newZ / moonTranformation * moveMouseX;
	var newY = newZ / moonTranformation * moveMouseY;
	
	mvTranslate([newX, -newY, newZ]);
//	mvTranslate([0, 0, newZ]);
    mvRotate(180, [1, 0, 0]);
    
	
	mvTranslate([-2, 0, 0]);
	
	mvRotateRad(Math.PI/2 - Math.acos(newX/moonTranformation),[0,-1,0]);
	mvRotateRad(Math.PI/2 - Math.acos(newY/moonTranformation),[1,0,0]);

    multMatrix(moonRotationMatrix);
    
//    mvTranslate([moveMouseX, moveMouseY, 0]);
    
    // mvTranslate([0, 0, -20]);
// mvRotate(180, [1, 0, 0]);
	
	gl.uniform1i(shaderProgram.useLightingUniform, true);
	gl.uniform3f(shaderProgram.ambientColorUniform, 0.2, 0.2, 0.2);

	var lightingDirection = Vector.create([ -0.25, -0.25, -1.0 ]);
	var adjustedLD = lightingDirection.toUnitVector().x(-1);
	var flatLD = adjustedLD.flatten();
	gl.uniform3fv(shaderProgram.lightingDirectionUniform, flatLD);

	gl.uniform3f(shaderProgram.directionalColorUniform, 0.1, 0.1, 0.1);
	
	
	//mvTranslate([(maxX - minX) / 2, (maxY - minY) / 2, (maxZ - minZ) / 2]);
	//log(maxX + " " + minX);
	mvTranslate([-(maxX + minX) / 2, -(maxY + minY) / 2, -(maxZ + minZ) / 2]);
	//mvTranslate([(Math.abs(maxX - minX)) / 2, 0, 0]);
	
    for(i in table.p) 
    {
    	mvPushMatrix();
    	
    	mvTranslate([table.p[i].x, table.p[i].y, table.p[i].z]);

    	mvRotateRad(table.p[i].rx, [1, 0, 0]);
    	mvRotateRad(table.p[i].ry, [0, 1, 0]);
    	mvRotateRad(table.p[i].rz, [0, 0, 1]);
    	
		mvScale([(table.p[i].s)/10, (table.p[i].s)/10, (table.p[i].s)/10]);  
    	
	    gl.bindBuffer(gl.ARRAY_BUFFER, table.p[i].vertexBuffer);
	    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, table.p[i].vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);

	    gl.bindBuffer(gl.ARRAY_BUFFER, table.p[i].normalBuffer);
	    gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, table.p[i].normalBuffer.itemSize, gl.FLOAT, false, 0, 0);
	    
	    gl.bindBuffer(gl.ARRAY_BUFFER, table.p[i].colorsBuffer);
	    gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, table.p[i].colorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
	    
	    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, table.p[i].indexBuffer);
	    setMatrixUniforms(gl, shaderProgram);

	    gl.drawElements(gl.TRIANGLES, table.p[i].indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

		mvPopMatrix();
    }
    for(i in table.j) 
    {
    	mvPushMatrix();

    	mvTranslate([table.j[i].p1value.x, table.j[i].p1value.y, table.j[i].p1value.z]);

    	var dx = table.j[i].p1value.x - table.j[i].p2value.x;
    	var dy = table.j[i].p1value.y - table.j[i].p2value.y;
    	var dz = table.j[i].p1value.z - table.j[i].p2value.z;
    	
    	
    	var leniuch = Math.sqrt(dx * dx + dy * dy + dz * dz);

    	var leny = Math.sqrt(dx * dx + dz * dz);
    	
    	if (leny != 0)
    	{
    		if (dx < 0)
    			mvRotateRad(Math.acos(dz/leny), [0, -1, 0]); //ok
    		else
    			mvRotateRad(Math.acos(dz/leny), [0, 1, 0]); //ok
    	}
    	
    	if (leniuch != 0)
    	{
    		if (dy < 0)
    			mvRotateRad(Math.acos(leny/leniuch), [1, 0, 0]);
    		else
    			mvRotateRad(Math.acos(leny/leniuch), [-1, 0, 0]);
    	}
    	if (leniuch != 0)
    		mvScale([1/10, 1/10, leniuch]);

    	
	    gl.bindBuffer(gl.ARRAY_BUFFER, table.j[i].vertexBuffer);
	    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, table.j[i].vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
	    gl.bindBuffer(gl.ARRAY_BUFFER, table.j[i].normalBuffer);
	    gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, table.j[i].normalBuffer.itemSize, gl.FLOAT, false, 0, 0);
	    
	    gl.bindBuffer(gl.ARRAY_BUFFER, table.j[i].colorsBuffer);
	    gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, table.j[i].colorsBuffer.itemSize, gl.FLOAT, false, 0, 0);
	    
	    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, table.j[i].indexBuffer);
	    setMatrixUniforms(gl, shaderProgram);
	    gl.drawElements(gl.TRIANGLES, table.j[i].indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

		mvPopMatrix();
    }
	//mvPopMatrix();
    
    if (draw == 1) {
  	  setTimeout(function() { drawScene(gl, shaderProgram, table); }, 15);
  	  draw = 0;	
    }
    else
    {
    	finishDrawing = 1;
    }
}

var gl;
var shaderProgram;
var table;

function webGLStart() {
  var canvas = document.getElementById("framstiks-canvas");
  gl = initGL(canvas);
  shaderProgram = initShaders(gl);
  //var squareVertexPositionBuffer = gl.createBuffer();
  //var squareVertexColorBuffer = gl.createBuffer();
  //var cubeVertexIndexBuffer = gl.createBuffer();
  //document.getElementById("f0").
  table = parse(gl, document.getElementById("f0").value);
  

  //initBuffers(gl, squareVertexPositionBuffer, squareVertexColorBuffer, cubeVertexIndexBuffer);
  
  gl.clearColor(0, 0, 0, 0.7);

  gl.clearDepth(1.0);

  gl.enable(gl.DEPTH_TEST);
  gl.depthFunc(gl.LEQUAL);

  canvas.onmousedown = handleMouseDown;
  document.onmouseup = handleMouseUp;
  document.onmousemove = handleMouseMove;
  
  if (canvas.addEventListener)
      /** DOMMouseScroll is for mozilla. */
	  canvas.addEventListener('DOMMouseScroll', wheel, false);
  canvas.onmousewheel = wheel;

  //alert("test" + table);
  //alert(table[0].vertexBuffer);
  if (draw == 1) {
	  setTimeout(function() { drawScene(gl, shaderProgram, table); }, 15);
	  draw = 0;
  }
}
